package emulator.shell.GUI;

import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import java.util.Map.Entry;
import java.util.prefs.Preferences;

import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import emulator.hardware.nmos6502.Cpu6502;
import emulator.shell.GUI.menu.WindowConfiguration;
import emulator.shell.GUI.menu.WindowDebug;
import emulator.shell.GUI.menu.WindowIEC;
import emulator.shell.GUI.menu.WindowMemory;
import emulator.shell.GUI.menu.WindowVia;
import emulator.shell.GUI.menu.WindowSettings;
import emulator.shell.GUI.windows.WindowManager;

public class WindowData implements Observer
{
	static Logger logger = LogManager.getLogger(WindowData.class.getName());
	private WindowManager window_manager;
	private ImageIcon menu_selected_icon;
	private ImageIcon menu_unselected_icon;
	private HashMap<Integer, JMenuItem> window_menu_map;
	private ConsoleFrame console;
	public static final int WINDOW_ID_MEMORY = 1;	
	public static final int WINDOW_ID_CONFIGURATION = 2;
	public static final int WINDOW_ID_DEBUG = 3;
	public static final int WINDOW_ID_IECLOG = 4;
	public static final int WINDOW_ID_VIA1 = 5;
	public static final int WINDOW_ID_VIA2 = 6;
	public static final int WINDOW_ID_SETTINGS = 7;

	public WindowData(String appName, ConsoleFrame console)
	{
		this.console = console;
		window_manager = new WindowManager(appName);
		window_manager.addObserver(this);
    	menu_selected_icon = new ImageIcon("images/menu_selected_icon.png");
    	menu_unselected_icon = new ImageIcon("images/menu_unselected_icon.png");
		window_menu_map = new HashMap<Integer, JMenuItem>();
	}

	void addWindowMenu(JMenu menu, String caption, int window_id)
	{
		try {
			JMenuItem menu_item = new JMenuItem(caption, menu_unselected_icon);
			menu_item.addActionListener(createListenerForId(window_id));
			window_menu_map.put(window_id, menu_item);
			menu.add(menu_item);
		}
		catch (Exception ex)
		{
			logger.info("Window \""+caption+"\" not available.", ex);
		}
	}

	private ActionListener createListenerForId(int window_id)
	{
		ActionListener windowListener = null;
		if (window_id == WINDOW_ID_MEMORY)
			windowListener = new WindowMemory(window_manager, window_id, console.getAssembler(), console.getMemory());
		else if (window_id == WINDOW_ID_CONFIGURATION)
			windowListener = new WindowConfiguration(window_manager, window_id, console.getBus());
		else if (window_id == WINDOW_ID_DEBUG)
			windowListener = new WindowDebug(window_manager, window_id, console.getAssembler(), (Cpu6502)console.getCpu(), console.getMemory());
		else if (window_id == WINDOW_ID_IECLOG)
			windowListener = new WindowIEC(window_manager, window_id, console.getIecSim(), console.getVia1(), (Cpu6502)console.getCpu(), console.getPortStateHistory1(), console.getPortStateHistory2());
		else if (window_id == WINDOW_ID_VIA1)
			windowListener = new WindowVia(window_manager, window_id, "VIA 1", console.getVia1(), (Cpu6502)console.getCpu(), console.getPortStateHistory1());
		else if (window_id == WINDOW_ID_VIA2)
			windowListener = new WindowVia(window_manager, window_id, "VIA 2", console.getVia2(), (Cpu6502)console.getCpu(), console.getPortStateHistory2());
		else if (window_id == WINDOW_ID_SETTINGS)
			windowListener = new WindowSettings(window_manager, window_id, console.getClock());
		return windowListener;
	}
	
	@Override
	public void update(Observable arg0, Object arg1)
	{
		updateWindowStates();
	}

	void updateWindowStates()
	{
		for (Entry<Integer, JMenuItem> entry : window_menu_map.entrySet())
		{
			if (window_manager.isWindowActive(entry.getKey()))
				entry.getValue().setIcon(menu_selected_icon);
			else
				entry.getValue().setIcon(menu_unselected_icon);
		}
	}

	public void saveWindowStates()
	{
	    Preferences cfg = Preferences.userNodeForPackage(this.getClass());
		for (Entry<Integer, JMenuItem> entry : window_menu_map.entrySet())
		{
			cfg.putBoolean(window_manager.getAppName() + "$" + entry.getKey(), window_manager.isWindowActive(entry.getKey()));
		}
	}
	
	public void restoreWindowStates()
	{
	    Preferences cfg = Preferences.userNodeForPackage(this.getClass());
		for (Entry<Integer, JMenuItem> entry : window_menu_map.entrySet())
		{
			boolean makeActive = cfg.getBoolean(window_manager.getAppName() + "$" + entry.getKey(), false);
			if (makeActive != window_manager.isWindowActive(entry.getKey()))
				entry.getValue().doClick();
		}
		
	}
}